/*
 * main.h
 *
 *  Created on: 25/09/2011
 *      Author: utn_so
 */

#ifndef MAIN_H_
#define MAIN_H_

#include <stdio.h>
#include <ctype.h> /* ----> Funcion Toupper */
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/mman.h>
#include <fuse.h>
#include <errno.h>
#include <pthread.h>
#include <fcntl.h>
#include <unistd.h>
#include <stddef.h>
#include <stdint.h>
#include <unicode/utypes.h>
#include <unicode/ustring.h>
#include "config.h"
#include "log.h"
#include "sockets.h"
#include "estructuras.h"

#define TAMSECTOR 512
#define FINARCHIVO 0xfffffff
#define LISTARDIRECTORIO 0x58
#define NOMBRELARGO 0x0F
#define ENTRADADIR 0x10
#define ENTRADAARC 0x20
#define NOHAYMASENTRADAS 0x00
#define RETORNADIRECTORIO 0x2E
#define ENTRADABORRADA 0xE5
#define HANDSHAKE 0
#define Retorno_Error 1
#define pathCfg "/CfgPFS.cfg"

/*************** FUNCIONES FUSE *************************/


/********************************************************/
/************ FUNCIONES PFS *****************************/


t_config abrirArchivoConfig();
char *setearCfgPFS(char *token);
int16_t stringAInt16(char *pPuerto);
void separaCadenas(const char *directorio, char **directorioABuscar,char **directorioACrear);
int32_t compararCadenas(const char *to, const char *from, char **nombreTo,char **nombreFrom);
uint32_t obtenerClusterSiguiente(uint32_t clusterActual);
char *buscarNombre(const char *path);
char *armarPath(const char* path);
uint32_t armarClusterInicial(uint16_t clusterHigh, uint16_t clusterLow);
uint32_t buscarEntrada(uint32_t clusterInicial, char *entradaABuscar,uint32_t *offsetDirectorio, stDirectoryConNombreLargo *stEntradaLeida);
void buscarEntradaLibre (uint32_t clusterDirectorio,uint32_t *offset, char **cluster);
void modificarEntradaDirectorio (stDirectoryConNombreLargo stEntrada,uint32_t offsetDirectorio, uint32_t nroClusterDirectorio);
void leerEntradaDeDirectorio (stDirectoryConNombreLargo *stEntradaDirARetornar,char *sector,uint32_t *cantLeido);
uint32_t leerSubDirectorios(char *entradaABuscar, uint32_t *offsetDirectorio,stDirectoryConNombreLargo *stEntradaLeida, uint32_t *clusterDirectorio);
void renombrarArchivo (const char *from,char *nuevoNombre);
uint32_t moverArchivo(const char *from,const char *to,char *nuevoNombre);
uint32_t obtenerUltimoCLusterLeido(uint32_t clusterInicial, uint32_t offset);
uint32_t obtenerUltimoCLusterEscrito (uint32_t clusterInicial, uint32_t offset);
void leerArchivos (uint32_t clusterInicial, char **cluster);
uint32_t escribeArchivos(uint32_t clusterInicial, char *Payload);
uint32_t modificarArchivos(uint32_t clusterInicial, char *Payload,uint32_t offset,size_t size);
uint32_t obtenerNuevoCluster(uint32_t clusterInicial,uint32_t offset);

void achicarArchivo(uint32_t clusterInicial,uint32_t tamAnterior,uint32_t nuevoTam);
void agrandarArchivo(uint32_t clusterActual,uint32_t tamAnterior,uint32_t nuevoTam);
uint32_t cantClustersTruncate(uint32_t tamAnterior,uint32_t nuevoTam);
void quitarClusters(uint32_t ultimoClusArchivo,uint32_t nuevoUltimoCluster);
void asignarNuevoCluster(uint32_t ultimoClusArchivo,uint32_t nuevoCluster);
uint32_t obtenerAnteUltimo(uint32_t clusterInicial,uint32_t ultimoCluster);
uint32_t obtenerUltimoCluster(uint32_t clusterInicial);
uint32_t obtenerclusterNuevo();
void crearEntradasComunes(uint32_t clusterDirectorio,uint32_t nuevoClusterDir);

/********************************************************/
/****************** DIRECCIONAMIENTO ********************/
uint32_t obtenerPrimerSectorDataRegion();
uint32_t obtenerPrimerSectorDeUnCluster(uint32_t nroCluster);
uint32_t *deClusterASectores(uint32_t nroCluster);
uint32_t deSectorACluster(uint32_t nroSector);
uint32_t calcularPosicion(uint32_t nroSector);
uint32_t deClusterABloque(uint32_t nroCluster);
uint32_t obtenerPrimerSectorDeUnBloque(uint32_t nroBloque);
uint32_t cantidadClustersDelBloque();
void liberarConexion (int32_t *nroSocket);
void buscarConexionLibre(int32_t **conexiones);
void armarCluster(uint32_t nroSector, char *dataEscritura, char **cluster);
void enviarPeticiones(uint32_t nroSector,char **pBloque);
int32_t enviarPeticionesEscritura (uint32_t nroSector, char *dataEscritura);
void CrearPoolConexiones(char *pDirIp, int16_t puerto);
void borrarEntradaDirectorio(uint32_t clusterDirectorio,uint32_t offset,stDirectoryConNombreLargo *stDirABorrar);


/********************************************************/
/****************** CONSOLA *****************************/
void ejecutarConsola();
void interfazConsola();
void procesaFsInfo();
void procesaFInfo(char *pathArchivo);
int32_t obtenerNumeroDeOperacion(char *data);
void procesarConsola(char *data);

/********************************************************/
/***************** UTF 16 - UTF 8 **********************/
uint8_t armarNombreLargo(stLongFileName stArchivosNombreLargo, char **nombreLargo);
int8_t traducirArchivoNombreLargo(uint16_t *archNombreLargo, char *nombreCorto,
		int16_t largoArchivo);
void cargarNombreLargo(stLongFileName *stNombreLargoAEscribir,char *directorioACrear);
void cargarNombreCorto(stDirectoryTable *stDirAEscribir, char *directorioACrear);
void crearEntradasDirectorio(stDirectoryTable *stDirAEscribir,stLongFileName *stNombreLargoAEscribir, char *nombre);
void cargarEntradaVacia(stLongFileName *stNombreLargoAEscribir);
void traducirLittleEndian(uint32_t nroCluster,uint16_t *clusterHigh,uint16_t *clusterLow);

/*******************************************************/
void loguearListaClusters(const char *path,uint32_t clusterInicial);
void handshake (int32_t socket);
/******************* CACHE *****************************/


int32_t obtenerInterfazCache (char  **interfaz);
int32_t obtenerNombreArchivo (char  **nombreCompleto, char *nombre);
int32_t contenidoBloque (char **contenido, int32_t nroBloque);
void cache_dump();

t_listaArchivos *crearLista ();
int32_t obtenerCantidad ();
void agregarEnLaLista (uint32_t clusterInicial, uint32_t fileSize, char *nombre);
void agregarApertura (char *nombre);
t_nodoArchivos *buscarEnLaLista (char *nombre);
int32_t buscarCluster (t_nodoArchivos *nodoArchivo, uint32_t clusterInicial);
int32_t agregarCluster(t_nodoArchivos *nodoArchivo, uint32_t clusterInicial,const char *dataCluster,size_t size);
int32_t agregarClusterEscritura(t_nodoArchivos *nodoArchivo, uint32_t clusterInicial,const char *dataCluster,size_t size);
int32_t modificarCluster(t_nodoArchivos *nodoArchivo, uint32_t clusterInicial,const char *dataCluster,size_t size,uint32_t offset);
void quitarNodo(t_nodoArchivos *nodoArchivo);
int32_t algoritmoReemplazoLRU(t_nodoArchivos *nodoArchivo,uint32_t clusterInicial,const char *dataCluster,size_t size);
/*******************************************************/
/******************* ATIENDE FAT REGION ****************/
void atiendeFatRegion();
void leerFatRegion ();
int32_t recorroBitVector (int32_t cantClusters);
void limpiarBitVector(uint32_t cantidadBloque,uint32_t nroBloque,uint32_t offset);
void armarFatRegion(uint32_t cantSecBloque,uint32_t offset,char **dataEscritura);
#endif /* MAIN_H_ */

